﻿using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Description;

namespace jbt.CodeCandy.AsTrEAM.WCF
{
    /// <summary>
    /// Creates a service host what can host an <see cref="IStreamManagerService"/>.
    /// </summary>
    public class StreamManagerServiceHostFactory : ServiceHostFactory
    {
        private static void ConfigureServiceHost(ServiceHostBase serviceHost)
        {
            if (!serviceHost.Description.Behaviors.Contains(typeof(ServiceMetadataBehavior)))
            {
                serviceHost.Description.Behaviors.Add(new ServiceMetadataBehavior());
            }

            var defaultEndpointContractName = typeof(IStreamManagerService).FullName;

            var defaultEndpointBinding = new BasicHttpBinding();
            defaultEndpointBinding.MaxReceivedMessageSize = Int32.MaxValue;
            defaultEndpointBinding.TransferMode = TransferMode.Streamed;

            const string defaultEndpointAddress = "";

            var defaultEndpoint = serviceHost.AddServiceEndpoint(defaultEndpointContractName, defaultEndpointBinding, defaultEndpointAddress);

            var dispatcherSynchronizationBehavior = new DispatcherSynchronizationBehavior();
            dispatcherSynchronizationBehavior.AsynchronousSendEnabled = true;

            defaultEndpoint.EndpointBehaviors.Add(dispatcherSynchronizationBehavior);

            var mexEndpoint = new ServiceMetadataEndpoint();
            const string mexAddress = "mex";

            serviceHost.AddServiceEndpoint(mexEndpoint.Contract.Name, mexEndpoint.Binding, mexAddress);
        }

        /// <summary>
        /// Creates a service host what can host an <see cref="IStreamManagerService"/>.
        /// </summary>
        /// <param name="constructorString">
        /// The initialization data passed to the <see cref="ServiceHostBase"/> instance being constructed by the factory.
        /// </param>
        /// <param name="baseAddresses">
        /// The <see cref="Array"/> of type <see cref="Uri"/> that contains the base addresses for the service hosted.
        /// </param>
        /// <returns>
        /// A <see cref="ServiceHost"/> with specific base addresses what can host an <see cref="IStreamManagerService"/>.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// There is no hosting context provided or <paramref name="constructorString"/> is null or empty.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="baseAddresses"/> is null.
        /// </exception>
        public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
        {
            var serviceHost = base.CreateServiceHost(constructorString, baseAddresses);

            ConfigureServiceHost(serviceHost);

            return serviceHost;
        }
    }
}